﻿using System;
using System.Linq;
using JetBrains.Annotations;
using Kaleida.ServiceMonitor.Model.Email;
using Kaleida.ServiceMonitor.Model.Runtime;

namespace Kaleida.ServiceMonitor.Model
{
    public class ThresholdChangeEmailer : IServiceMonExtension
    {
        private readonly Monitor monitor;
    	[CanBeNull]private ScriptEmailSender emailSender;
        private SeverityLevel mostRecentSeverityLevel;
        readonly NotificationMessageBuilder builder = new NotificationMessageBuilder();

        public ThresholdChangeEmailer([NotNull] Monitor monitor)
        {
            if (monitor == null) throw new ArgumentNullException("monitor");
			
            this.monitor = monitor;
            UpdateMostRecentSeverityLevel();
        }

        public void ScriptCompilationComplete(ScriptCompilationCompleteEventArgs args)
        {
        }

        public void OnStartedMonitoring()
        {
            var compilation = monitor.State.ScriptCompilation;
            if (compilation != null)
            {
            	var recipients = compilation.CompiledScript.EmailOnThresholdChangeRecipients;
            	if (recipients.Any())
                {
                	var scriptName = monitor.Workspace.CurrentScript.Name;
                	emailSender = new ScriptEmailSender(scriptName, recipients);
					emailSender.Configure(monitor.Configuration);
                }
            }
            else
            {
            	emailSender = null;
            }
        }

    	public void OnOperationSuccessful(OperationSuccessfulEventArgs operationSuccessfulEventArgs)
        {
            SendEmailIfChangeInSeverity();
        }

        public void OnOperationFailed(OperationFailedEventArgs operationFailedEventArgs)
        {
            SendEmailIfChangeInSeverity();
        }

        public void OnErrorsAcknowledged()
        {
            SendEmailIfChangeInSeverity();
        }

        private void SendEmailIfChangeInSeverity()
        {
            var message = BuildMessageIfChangeInSeverity();

			if (message != null && emailSender != null)
				emailSender.TrySendEmail(message);
        }

        [CanBeNull]
		private NotificationMessage BuildMessageIfChangeInSeverity()
        {
            lock (this)
            {
                if (monitor.State.ToSeverityLevel() != mostRecentSeverityLevel)
                {
                    var message = builder.BuildThresholdChangeSummary(monitor, mostRecentSeverityLevel);
                    UpdateMostRecentSeverityLevel();
                    return message;
                }
                return null;
            }
        }

        private void UpdateMostRecentSeverityLevel()
        {
            mostRecentSeverityLevel = monitor.State.ToSeverityLevel();
        }
	}
}
